package com.heo.music.player.handler;

import lombok.extern.slf4j.Slf4j;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.ServletRequestBindingException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
import org.springframework.web.multipart.MaxUploadSizeExceededException;
import org.springframework.web.multipart.MultipartException;
import org.springframework.web.multipart.support.MissingServletRequestPartException;
import org.springframework.web.servlet.NoHandlerFoundException;

import javax.validation.ConstraintViolationException;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;

/**
 * 表单验证不通过异常捕获
 *
 * @author 星天无极
 **/
@ControllerAdvice
@Order(value = 0)
@Slf4j
public class RequestExceptionHandler {

    private static final Integer MESSAGE_MAX_LENGTH = 100;

    @ResponseBody
    @ExceptionHandler(BindException.class)
    public ResponseEntity<Map<String, Object>> handler(BindException e) {
        log.error(e.getMessage());

        Map<String, Object> map = new LinkedHashMap<>();
        Set<String> validErrorList = new LinkedHashSet<>();
        BindingResult result = e.getBindingResult();
        for (FieldError fieldError : result.getFieldErrors()) {
            validErrorList.add(fieldError.getDefaultMessage());
        }
        String message = String.join(",", validErrorList);
        if (message.length() > MESSAGE_MAX_LENGTH) {
            message = "参数错误";
        }
        map.put("message", message);
        map.put("details", validErrorList);

        //返回错误信息
        return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(map);
    }

    @ResponseBody
    @ExceptionHandler(NoHandlerFoundException.class)
    public ResponseEntity<Map<String, String>> handler(NoHandlerFoundException e) {
        log.info(e.getMessage());
        Map<String, String> map = new LinkedHashMap<>();
        map.put("message", "api not found");
        return ResponseEntity.status(HttpStatus.NOT_FOUND).body(map);
    }

    @ResponseBody
    @ExceptionHandler(MissingServletRequestPartException.class)
    public ResponseEntity<Map<String, String>> handler(MissingServletRequestPartException e) {
        log.error(e.getMessage());
        Map<String, String> map = new LinkedHashMap<>();
        map.put("message", "参数校验错误");
        map.put("details", e.getMessage());
        return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(map);
    }

    @ResponseBody
    @ExceptionHandler(HttpMessageNotReadableException.class)
    public ResponseEntity<Map<String, String>> handler(HttpMessageNotReadableException e) {
        log.error(e.getMessage());
        Map<String, String> map = new LinkedHashMap<>();
        map.put("message", "参数错误");
        return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(map);
    }

    @ResponseBody
    @ExceptionHandler(ServletRequestBindingException.class)
    public ResponseEntity<Map<String, String>> handler(ServletRequestBindingException e) {
        log.error(e.getMessage());
        Map<String, String> map = new LinkedHashMap<>();
        map.put("message", "缺少请求参数");
        map.put("details", e.getMessage());
        return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(map);
    }

    @ResponseBody
    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    public ResponseEntity<Map<String, String>> handler(HttpRequestMethodNotSupportedException e) {
        log.error(e.getMessage());
        Map<String, String> map = new LinkedHashMap<>();
        map.put("message", "请求方法不支持");
        map.put("details", e.getMessage());
        return ResponseEntity.status(HttpStatus.METHOD_NOT_ALLOWED).body(map);
    }

    @ResponseBody
    @ExceptionHandler(MethodArgumentTypeMismatchException.class)
    public ResponseEntity<Map<String, String>> handler(MethodArgumentTypeMismatchException e) {
        log.error(e.getMessage());
        Map<String, String> map = new LinkedHashMap<>();
        map.put("message", "接口不存在");
        return ResponseEntity.status(HttpStatus.NOT_FOUND).body(map);
    }

    @ResponseBody
    @ExceptionHandler(MaxUploadSizeExceededException.class)
    public ResponseEntity<Map<String, String>> handler(MaxUploadSizeExceededException e) {
        log.error(e.getMessage());
        Map<String, String> map = new LinkedHashMap<>();
        map.put("message", "文件过大");
        map.put("details", e.getMessage());
        return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(map);
    }

    @ResponseBody
    @ExceptionHandler({MultipartException.class, ConstraintViolationException.class})
    public ResponseEntity<Map<String, String>> handler(Exception e) {
        log.error(e.getMessage());
        Map<String, String> map = new LinkedHashMap<>();
        map.put("message", "请求错误");
        map.put("details", e.getMessage());
        return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(map);
    }


}
